﻿namespace GoodAdmin.Core;

public static class DbContext
{
    public static readonly DbConnectionOptions DbConfigs = App.GetOptions<DbConnectionOptions>();

    /// <summary>
    /// SqlSugar 数据库实例
    /// </summary>
    public static readonly SqlSugarClient Db = new(DbConfigs.ConnectionConfigs.Adapt<List<ConnectionConfig>>(), 
        db =>
        {
            DbConfigs.ConnectionConfigs.ForEach(config => {
                var dbProvider = db.GetConnectionScope(config.ConfigId);
                SetDbAop(dbProvider);
            });
        });

    /// <summary>
    /// Db Aop设置
    /// </summary>
    /// <param name="db"></param>
    public static void SetDbAop(SqlSugarScopeProvider db)
    {
        var config = db.CurrentConnectionConfig;
        //设置超时时间，单位秒
        db.Ado.CommandTimeOut = 30;

        //如果不是正式环境，打印操作日志
        if (!App.WebHostEnvironment.IsProduction())
        {
            db.Aop.OnLogExecuting = (sql, paras) =>
            {
                if (sql.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase))
                    Console.ForegroundColor = ConsoleColor.Green;
                if (sql.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase) || sql.StartsWith("INSERT", StringComparison.OrdinalIgnoreCase))
                    Console.ForegroundColor = ConsoleColor.White;
                if (sql.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase))
                    Console.ForegroundColor = ConsoleColor.Blue;
                Console.WriteLine($"【{DateTime.Now} ——执行SQL】\r\n {UtilMethods.GetSqlString(config.DbType, sql, paras)} \r\n");
            };
        }
        //记录错误sql
        db.Aop.OnError = (ex) =>
        {
            if (ex.Parametres == null) return;
            Console.ForegroundColor = ConsoleColor.Red;
            var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value));
            Console.WriteLine($"【{DateTime.Now} ——错误SQL——{config.ConfigId}】\r\n  {UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres)} \r\n");
        };
        //数据操作
        db.Aop.DataExecuting = (oldValue, entityInfo) =>
        {
            //插入
            if (entityInfo.OperationType == DataFilterType.InsertByObject)
            {
                //类型为long的雪花Id主键
                if (entityInfo.EntityColumnInfo.IsPrimarykey && !entityInfo.EntityColumnInfo.IsIdentity && entityInfo.EntityColumnInfo.PropertyInfo.PropertyType == typeof(long))
                {
                    var idValue = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
                    if (idValue == null || (long)idValue == 0)
                    {
                        entityInfo.SetValue(Yitter.IdGenerator.YitIdHelper.NextId());
                    }
                }
                if (entityInfo.PropertyName == nameof(BaseEntity.CreateTime))
                    entityInfo.SetValue(DateTime.Now);
                //操作者信息
                if (App.User != null)
                {
                    if (entityInfo.PropertyName == nameof(BaseEntity.CreateUserId))
                        entityInfo.SetValue(App.User?.FindFirst(ClaimConst.UserId)?.Value);
                }
            }
            //更新
            else if (entityInfo.OperationType == DataFilterType.UpdateByObject)
            {
                if (entityInfo.PropertyName == nameof(BaseEntity.UpdateTime))
                    entityInfo.SetValue(DateTime.Now);
                if (App.User != null)
                {
                    if (entityInfo.PropertyName == nameof(BaseEntity.UpdateUserId))
                        entityInfo.SetValue(App.User?.FindFirst(ClaimConst.UserId)?.Value);
                }
            }
        };
    }
}